﻿namespace LightCAD.Core.Elements.Basic
{
    public class LcRasterImage : LcElement
    {
        public Vector2 FirstPoint;
        public Vector2 EndPoint;
        public double Width;
        public double Height;
        public double RotateAngle;
        public double ScaleValue;
        public string ImagePath;

        public Box2 Box2D;

        public LcRasterImage()
        {
            this.Type = BuiltinElementType.RasterImage;
        }

        public override LcElement Clone()
        {
            var clone = new LcRasterImage();
            clone.Copy(this);
            return clone;
        }

        public void Set(Vector2 start = null, Vector2 end = null, double? width = null, double? height = null, double? rotate = null, double? scale = null, string imagePath = "", bool fireChangedEvent = true)
        {
            if (!fireChangedEvent)
            {
                if (start != null) this.FirstPoint = start;
                if (end != null) this.EndPoint = end;
            }
            else
            {
                bool chg_start = (start != null && start != this.FirstPoint);
                if (chg_start)
                {
                    OnPropertyChangedBefore(nameof(start), this.FirstPoint, start);
                    var oldValue = this.FirstPoint;
                    this.FirstPoint = start;
                    OnPropertyChangedAfter(nameof(start), oldValue, this.FirstPoint);
                }

                bool chg_end = (end != null && end != this.EndPoint);
                if (chg_end)
                {
                    OnPropertyChangedBefore(nameof(end), this.EndPoint, end);
                    var oldValue = this.EndPoint;
                    this.EndPoint = end;
                    OnPropertyChangedAfter(nameof(end), oldValue, this.EndPoint);
                }
                this.Box2D = new Box2().SetFromPoints(this.FirstPoint, this.EndPoint);

                bool chg_width = (width != null && width != this.Width);
                if (chg_width)
                {
                    OnPropertyChangedBefore(nameof(width), this.Width, width);
                    var oldValue = this.Width;
                    this.Width = Math.Round(width.Value);
                    OnPropertyChangedAfter(nameof(width), oldValue, this.Width);
                }

                bool chg_height = (height != null && height != this.Height);
                if (chg_height)
                {
                    OnPropertyChangedBefore(nameof(height), this.Height, height);
                    var oldValue = this.Height;
                    this.Height = Math.Round(height.Value);
                    OnPropertyChangedAfter(nameof(height), oldValue, this.Height);
                }

                bool chg_rotate = (rotate != null && rotate != this.RotateAngle);
                if (chg_rotate)
                {
                    OnPropertyChangedBefore(nameof(rotate), this.RotateAngle, rotate);
                    var oldValue = this.RotateAngle;
                    this.RotateAngle = Math.Round(rotate.Value);
                    OnPropertyChangedAfter(nameof(rotate), oldValue, this.RotateAngle);
                }

                bool chg_scale = (scale != null && scale != this.ScaleValue);
                if (chg_scale)
                {
                    OnPropertyChangedBefore(nameof(scale), this.ScaleValue, scale);
                    var oldValue = this.ScaleValue;
                    this.ScaleValue = Math.Round(scale.Value);
                    OnPropertyChangedAfter(nameof(scale), oldValue, this.ScaleValue);
                }

                bool chg_image_path = (imagePath != "" && imagePath != this.ImagePath);
                if (chg_image_path)
                {
                    OnPropertyChangedBefore(nameof(imagePath), this.ImagePath, imagePath);
                    var oldValue = this.ImagePath;
                    this.ImagePath = imagePath;
                    OnPropertyChangedAfter(nameof(imagePath), oldValue, this.ImagePath);
                }
            }
        }

        public override void Translate(double dx, double dy)
        {
            var ts = new Vector2(this.FirstPoint.X + dx, this.FirstPoint.Y + dy);
            var te = new Vector2(this.EndPoint.X + dx, this.EndPoint.Y + dy);
            Set(ts, te);
            ResetBoundingBox();
        }

        public override Box2 GetBoundingBox()
        {
            return new Box2().SetFromPoints(this.FirstPoint, this.EndPoint);
        }
        public override Box2 GetBoundingBox(Matrix3 matrix)
        {
            return new Box2().SetFromPoints(matrix.MultiplyPoint(this.FirstPoint), matrix.MultiplyPoint(this.EndPoint));
        }

        public override bool IntersectWithBox(Polygon2d testPoly, List<RefChildElement> intersectChildren = null)
        {
            var thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                //如果元素盒子，与多边形盒子不相交，那就可能不相交
                return false;
            }
            return GeoUtils.IsPolygonIntersectLine(testPoly.Points, this.FirstPoint, this.EndPoint)
                || GeoUtils.IsPolygonContainsLine(testPoly.Points, this.FirstPoint, this.EndPoint);
        }

        public override bool IncludedByBox(Polygon2d testPoly, List<RefChildElement> includedChildren = null)
        {
            var thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                return false;
            }
            return GeoUtils.IsPolygonContainsLine(testPoly.Points, this.FirstPoint, this.EndPoint);
        }
    }
}
